// phalanx array.hpp.cu header file

// Copyright (c) 2010 - 2011 Kohei Takahashi (Flast).
// Distributed under the MIT license. for more detail see COPYING.

// Redefinition C++0x STL array
//              Boost's array

#ifndef IG_PHALANX_ARRAY_HPP_CU_ONCE_
#define IG_PHALANX_ARRAY_HPP_CU_ONCE_

#include <phalanx/config.hpp.cu>
#include <phalanx/detail/retypedef.hpp.cu>

#include <phalanx/iterator/reverse_iterator.hpp.cu>

#include <phalanx/type_traits/detail/base_traits.hpp.cu>

#include <phalanx/utility/addressof.hpp.cu>

namespace phalanx
{

// XXX: array must be satisfy requirements of aggregate type.
//      Therefore, users can initialize with braced initializer list.
template < typename T,
  typename traits_detail::base_traits< T >::size_type N >
struct array
{
    typedef traits_detail::base_traits< T > traits_type;
    PHALANX_PP_RETYPEDEF( traits_type, value_type );
    PHALANX_PP_RETYPEDEF( traits_type, pointer );
    PHALANX_PP_RETYPEDEF( traits_type, const_pointer );
    PHALANX_PP_RETYPEDEF( traits_type, reference );
    PHALANX_PP_RETYPEDEF( traits_type, const_reference );
    PHALANX_PP_RETYPEDEF( traits_type, size_type );
    PHALANX_PP_RETYPEDEF( traits_type, difference_type );
    typedef typename traits_type::pointer                 iterator;
    typedef typename traits_type::const_pointer           const_iterator;
    typedef ::phalanx::reverse_iterator< iterator >       reverse_iterator;
    typedef ::phalanx::reverse_iterator< const_iterator > const_reverse_iterator;

    static const size_type size_value = N;

    value_type impl_[ size_value ];

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    iterator
    begin( void )
    { return impl_; }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    const_iterator
    begin( void ) const
    { return impl_; }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    iterator
    end( void )
    { return begin() + size_value; }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    const_iterator
    end( void ) const
    { return begin() + size_value; }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    const_iterator
    cbegin( void ) const
    { return begin(); }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    const_iterator
    cend( void ) const
    { return end(); }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    reverse_iterator
    rbegin( void )
    { return reverse_iterator( end() ); }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    const_reverse_iterator
    rbegin( void ) const
    { return reverse_iterator( end() ); }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    reverse_iterator
    rend( void )
    { return reverse_iterator( begin() ); }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    const_reverse_iterator
    rend( void ) const
    { return reverse_iterator( begin() ); }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    const_reverse_iterator
    crbegin( void ) const
    { return rbegin(); }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    const_reverse_iterator
    crend( void ) const
    { return rend(); }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    size_type
    size( void ) const
    { return size_value; }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    size_type
    max_size( void ) const
    { return size_value; }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    bool
    empty( void ) const
    { return !size_value; }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    reference
    at( size_type x_ )
    { return begin()[ x_ ]; }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    const_reference
    at( size_type x_ ) const
    { return begin()[ x_ ]; }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    reference
    operator[]( size_type x_ )
    { return at( x_ ); }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    const_reference
    operator[]( size_type x_ ) const
    { return at( x_ ); }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    reference
    front( void )
    { return *begin(); }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    const_reference
    front( void ) const
    { return *begin(); }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    reference
    back( void )
    { return *rbegin(); }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    const_reference
    back( void ) const
    { return *rbegin(); }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    pointer
    data( void )
    { return addressof( front() ); }

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    const_pointer
    data( void ) const
    { return addressof( front() ); }
};

} // namespace phalanx

#endif // IG_PHALANX_ARRAY_HPP_CU_ONCE_

